package com.company.biz.user.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.company.biz.user.service.LoginService;
import com.company.biz.user.service.UserLogService;
import com.company.biz.user.service.UserService;
import com.company.common.enums.*;
import com.company.common.exception.BizException;
import com.company.common.util.*;
import com.company.user.entity.UserEntity;
import com.company.user.req.LoginReq;
import com.company.user.req.LogoutReq;
import com.company.user.resp.LoginResp;
import com.company.user.resp.UserInfoResp;
import com.company.user.vo.BaseData;
import com.company.user.vo.RespData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class LoginServiceImpl implements LoginService {


    @Resource
    private UserLogService userLogService;

    @Resource
    private UserService userService;

    @Value("${erp.any_password}")
    public Boolean anyPassword;

    /**
     * 用户登入
     * @param req
     */
    @Override
    public LoginResp login(LoginReq req) {
        RespData respData = new RespData();
        BaseData baseData = new BaseData();
        respData.setData(baseData);
        UserEntity userEntity = new UserEntity();
        //根据登录方式进行登录
        switch (req.getWay()) {
            case 1: {
                //账号密码登入
                userEntity = passwordLogin(req);
                break;
            }
            case 2: {
                //邮箱验证登录
                userEntity = messageCodeLogin(req, LoginReq.messageCodeType.EMAIL );
                break;
            }
            case 3:{
                //短信验证登录
                userEntity= messageCodeLogin(req, LoginReq.messageCodeType.MOBILEPHONE);
                break;
            }
            default:
                break;
        }
        UserInfoResp userInfoResp = new UserInfoResp();
        //生成token
        String token = req.getTerminal() + "-" + req.getUserType() + "-" + TokenGenerator.generateValue();
        log.info("生成的 token ==============> "+token);
        //生成Key的方式需要同步
        LoginResp bussData = new LoginResp();
        bussData.setToken(token);
        //添加日志
        userLogService.addUserLog(userEntity.getUserId(),req.getIp(),"用户登入",userEntity.getUserName()+"使用"+userEntity.getLoginName()+"登录");
        //返回是否是管理员
        if (userEntity.getUserType()==1) {
            bussData.setLoginRole("admin");
        }
        //放入redis中
        String json = JSONObject.toJSONString(userEntity);
        RedisUtil.set(token, json);
        RedisUtil.expire(token, 2, TimeUnit.HOURS);
        //RedisUtil.expire(token,30 , TimeUnit.SECONDS);
        baseData.setBussData(bussData);
        userEntity.copyTo(userInfoResp);
        bussData.setUserInfoResp(userInfoResp);
        return bussData;
    }

    /**
     * 退出登入
     * @param req
     * @return
     */
    @Override
    public LoginResp logout(LogoutReq req) {
        RedisUtil.del(req.getToken());
        return new LoginResp();
    }

    //账号密码登入
    public UserEntity passwordLogin(LoginReq req){
        //电话号码 登入用户名 邮箱
        String loginNameOrPhoneOrEmail = req.getMobilePhone();
        if (StringUtils.isBlank(loginNameOrPhoneOrEmail)) {
            loginNameOrPhoneOrEmail = req.getLoginName();
        }
        if (StringUtils.isBlank(loginNameOrPhoneOrEmail)) {
            loginNameOrPhoneOrEmail = req.getEmail();
        }
        if (StringUtils.isBlank(loginNameOrPhoneOrEmail)) {
            throw new BizException(UserErrorEnum.USER_NotNull);
        }

        UserEntity userEntity = null;
        userEntity = userService.getUserByLoginNameOrPhoneOrEmail(loginNameOrPhoneOrEmail);
        // 还空
        if (ObjectUtil.isEmpty(userEntity)) {
            throw new BizException(UserErrorEnum.USER_NOT_FOUND);
        }
        //如果在redis拿到LOCK_数据说明被锁
        if (RedisUtil.hasKey(ProjectConstants.USER_LOCK + userEntity.getUserId())) {
            throw new BizException(UserErrorEnum.USER_PASSWORD_LOCK);
        }
        //进行比对
        if (StringUtils.isEmpty(req.getPassword())) {
            throw new BizException(UserErrorEnum.USER_NULL_PASSWORD_ERROR);
        }
        boolean checkpw = BCryptUtil.checkpw(req.getPassword(), userEntity.getPassword());

        // TODO  测试环境的任何密码都OK
        if (anyPassword != null && anyPassword) {
            checkpw = true;
        }
        //密码不正确的话
        if (!checkpw) {
            //判断这个key是否存在
            if (RedisUtil.hasKey(ProjectConstants.USER_NUM + userEntity.getUserId())) {
                //存在就获取
                String s = RedisUtil.get(ProjectConstants.USER_NUM + userEntity.getUserId());
                Integer res = (Integer) JSONObject.parse(s);
                //如果次数不是10，就加1
                res = res + 1;
                String num = JSONObject.toJSONString(res);
                RedisUtil.set(ProjectConstants.USER_NUM + userEntity.getUserId(), num);
                //如果次数为10，就锁定
                if (res == 10) {
                    String json = JSONObject.toJSONString(ProjectConstants.USER_MOBILEPHONE + userEntity.getPhoneNumber());
                    RedisUtil.set(ProjectConstants.USER_LOCK + userEntity.getUserId(), json);
                    RedisUtil.expire(ProjectConstants.USER_LOCK + userEntity.getUserId(), 60 * 2, TimeUnit.SECONDS);
                    RedisUtil.del(ProjectConstants.USER_NUM + userEntity.getUserId());
                    throw new BizException(UserErrorEnum.USER_PASSWORD_LOCK);
                }
                throw new BizException(UserErrorEnum.USER_NAME_OR_PASSWORD_ERROR, "密码已错误" + num + "次");
            }
            else {
                //如果第一次输错就等于1
                String json = JSONObject.toJSONString(1);
                RedisUtil.set(ProjectConstants.USER_NUM + userEntity.getUserId(), json);
                RedisUtil.expire(ProjectConstants.USER_NUM + userEntity.getUserId(), 60 * 2, TimeUnit.SECONDS);
                throw new BizException(UserErrorEnum.USER_NAME_OR_PASSWORD_ERROR, "密码已错误" + 1 + "次");
            }
        }
        //如果登录成功  清空次数
        if (RedisUtil.hasKey(ProjectConstants.USER_NUM + userEntity.getUserId())) {
            RedisUtil.del(ProjectConstants.USER_NUM + userEntity.getUserId());
        }
        return userEntity;
    }
    //验证码登入
    public UserEntity messageCodeLogin(LoginReq req,String messageCodeType){
        String phoneOrEmail=req.getMobilePhone();
        if(StringUtils.isEmpty(phoneOrEmail)){
            phoneOrEmail=req.getEmail();
        }
        UserEntity userEntity = userService.getUserByLoginNameOrPhoneOrEmail(phoneOrEmail);
        if (ObjectUtil.isEmpty(userEntity)) {
            throw new BizException(UserErrorEnum.USER_NOT_FOUND);
        }
        String code = null;
        if(LoginReq.messageCodeType.MOBILEPHONE.equals(messageCodeType)){
            //redis获取验证码 TODO
             code = RedisUtil.get(req.getMobilePhone());
        }
        if(LoginReq.messageCodeType.EMAIL.equals(messageCodeType)){
            //redis获取验证码 TODO
             code = RedisUtil.get(req.getEmail());
            System.out.println("redis-------------"+code);
        }
        if(StringUtils.isEmpty(code)){
            throw new BizException("", "请先获取验证码!");
        }
        if (!req.getMessageCode().equals(code)) {
            throw new BizException("400", "验证码有误!");
        }
        return userEntity;
    }

}
